home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / a_utils / decomp.lha / decomp / disasm.c < prev    next >
C/C++ Source or Header  |  1988-01-12  |  11KB  |  526 lines

  1. /*
  2.  * Module: disasm.c
  3.  *
  4.  * Author: J. Reuter
  5.  *
  6.  * This module "disassembles" a function into pseudo-C code
  7.  * for data manipulation and pseudo-assembler code for all
  8.  * conditional test and branch instructions.  It makes no
  9.  * attempt to structure the code.
  10.  *
  11.  * This disassembler is used as a fallback when the fancy
  12.  * structuring code breaks.  This does not happen very often
  13.  * with PCC output.  Occasionally the Unix peephole optimizer will
  14.  * combine the last bits of code for several functions, causing
  15.  * the structuring code to break.
  16.  */
  17.  
  18. #include "defs.h"
  19. #include "machine.h"
  20. #include "labeltab.h"
  21. #include "objfile.h"
  22. #include "vartab.h"
  23.  
  24. extern char *typesuf[];
  25.  
  26. static struct operand {
  27.     int op_argval;
  28.     int op_indexed;
  29.     int op_index_rn;
  30.     int op_index_type;
  31.     char opstring[40];
  32. } operand[6];
  33.  
  34. disasm( addr, end_addr )
  35. address addr, end_addr;
  36. {
  37.     struct opcode *op;
  38.     VaxOpcode ins;
  39.     address insaddr;
  40.     unsigned char mode;
  41.     int argtype, amode, argno, argval;
  42.     int rn, type;
  43.     short offset;
  44.     struct nlist *s;
  45.     char *str;
  46.     struct llb *l;
  47.     struct relocation_info *r;
  48.  
  49.     /* initialize pass */
  50.     l = llb_first();
  51.     relo_first();
  52.     r = relo_next();
  53.  
  54.     /* the main loop */
  55.     while ( addr < end_addr ) {
  56.     argval = 0;
  57.  
  58.     while ( l->l_address < addr )
  59.         l = llb_next();
  60.  
  61.     if ( l != NULL && addr == l->l_address ) {
  62.         if ( l->caselab )
  63.         printf( "C%04d:", addr );
  64.         else
  65.         printf( "G%04d:", addr );
  66.     }
  67.  
  68.     ins = get_byte( addr );
  69.     addr += 1;
  70.     op = &opcode[ins];
  71.  
  72.     for (argno = 0; argno < op->numargs; argno++)
  73.         operand[argno].op_indexed = FALSE;
  74.  
  75.     for (argno = 0; argno < op->numargs; argno++) {
  76.  
  77.         str = operand[argno].opstring;
  78.  
  79.         argtype = op->argtype[argno];
  80.         if (is_branch_disp(argtype)) {
  81.         mode = 0xAF + ( (typelen(argtype) & ~T_UNSIGNED) << 4);
  82.         } else {
  83.         mode = get_byte( addr );
  84.         addr += 1;
  85.         }
  86.  
  87.         while ( r != NULL && addr > r->r_address )
  88.         r = relo_next();
  89.  
  90.         rn = regnm( mode );
  91.         type = typelen( argtype );
  92.         amode = addrmode(mode);
  93.  
  94.         if ( r != NULL && addr == r->r_address ) {
  95.  
  96.         if ( amode == LONGDISP || amode == LONGDISPDEF ) {
  97.  
  98.             argval = getdisp(addr, 4, rn, amode);
  99.             addr += 4;
  100.  
  101.         } else if ( amode == AUTOINC ) {
  102.  
  103.             if ( rn != PC ) {
  104.             printf( "ERR: strange relo autoinc reg\n" );
  105.             } else {
  106.             /* immediate values */
  107.             switch ( type & ~T_UNSIGNED ) {
  108.             case TYPL:
  109.                 argval = getdisp(addr, 4, rn, amode);
  110.                 addr += 4;
  111.                 break;
  112.  
  113.             default:
  114.                 printf( "ERR: strange relo autoinc %d\n", type );
  115.                 break;
  116.             }
  117.             }
  118.  
  119.         } else {
  120.             printf( "ERR: bad relo mode %d\n", amode );
  121.         }
  122.  
  123.         if ( r->r_extern ) {
  124.  
  125.             s = &symtab[r->r_symbolnum];
  126.  
  127.             if ( s->n_type == (N_EXT+N_UNDF) ) {
  128.  
  129.             if ( amode == LONGDISP || amode == LONGDISPDEF ) {
  130.                 char *def;
  131.  
  132.                 if ( amode == LONGDISPDEF ) {
  133.                 def = "*";
  134.                 type |= T_POINTER;
  135.                 } else {
  136.                 def = "";
  137.                 }
  138.  
  139.                 if ( rn == PC )
  140.                 sprintf( str, "%s%s", def,
  141.                     ext_sym( r->r_symbolnum, type, argval ) );
  142.                 else
  143.                 sprintf( str, "%s%s(r%02d)", def,
  144.                     ext_sym( r->r_symbolnum, type, argval ),
  145.                     rn );
  146.  
  147.             } else if ( amode == AUTOINC ) {
  148.                 sprintf( str, "%s", ext_sym( r->r_symbolnum, type,
  149.                             argval ) );
  150.             } else {
  151.                 printf( "ERR: ext relo mode %d\n", amode );
  152.             }
  153.             } else {
  154.             printf( "ERR: ext relo type %d\n", s->n_type );
  155.             }
  156.  
  157.         } else {        /* not r->r_extern */
  158.  
  159.             if ( amode == LONGDISP || amode == LONGDISPDEF ) {
  160.             char *def;
  161.  
  162.             if ( amode == LONGDISPDEF ) {
  163.                 def = "*";
  164.                 type |= T_POINTER;
  165.             } else {
  166.                 def = "";
  167.             }
  168.  
  169.             if ( rn == PC ) {
  170.                 switch ( r->r_symbolnum ) {
  171.                 case 4:
  172.                 /* static function */
  173.                 sprintf( str, "%s%s", def,
  174.                     int_sym( argval, type, C_TEXT ) );
  175.                 break;
  176.                 case 5:
  177.                 /* global function */
  178.                 sprintf( str, "%s%s", def,
  179.                     int_sym( argval, type, C_TEXT ) );
  180.                 break;
  181.                 case 6:
  182.                 /* static data, const, string */
  183.                 sprintf( str, "%s%s", def,
  184.                     int_sym( argval, type, C_DATA ) );
  185.                 break;
  186.                 case 7:
  187.                 /* global data, const, string */
  188.                 sprintf( str, "%s%s", def,
  189.                     int_sym( argval, type, C_DATA ) );
  190.                 break;
  191.                 case 8:
  192.                 /* bss */
  193.                 sprintf( str, "%s%s", def,
  194.                     int_sym( argval, type, C_BSS ) );
  195.                 break;
  196.                 default:
  197.                 printf( "ERR: bad relo symbolnum %d\n",
  198.                        r->r_symbolnum );
  199.                 break;
  200.                 }
  201.             } else {
  202.                 /* other registers? */
  203.                 sprintf( str, "%s%d(r%02d)", def, argval, rn );
  204.                 printf( "\targ %d int longdisp sym#%d pcrel %d len %d reg %d\n",
  205.                    argno, r->r_symbolnum, r->r_pcrel, r->r_length, rn );
  206.             }
  207.  
  208.             } else if ( amode == AUTOINC ) {
  209.  
  210.             switch ( r->r_symbolnum ) {
  211.             case 6:
  212.                 /* static data */
  213.                 sprintf( str, "%s", int_sym( argval, type, C_DATA ) );
  214.                 break;
  215.             case 8:
  216.                 /* static bss */
  217.                 sprintf( str, "%s", int_sym( argval, type, C_BSS ) );
  218.                 break;
  219.             default:
  220.                 printf( "ERR: auto relo symnum %d\n", r->r_symbolnum );
  221.                 break;
  222.             }
  223.             } else {
  224.             printf( "ERR: int relo mode %d\n", amode );
  225.             }
  226.         }
  227.  
  228.         } else {        /* no relo info */
  229.  
  230.         switch (amode) {
  231.         case LITSHORT:
  232.         case LITUPTO31:
  233.         case LITUPTO47:
  234.         case LITUPTO63:
  235.             if ( type == TYPF || type == TYPD )
  236.             sprintf( str, "%s", fltimm[mode] );
  237.             else
  238.             sprintf( str, "%d", mode );
  239.             argval = mode;
  240.             break;
  241.  
  242.         case INDEX:
  243.             operand[argno].op_indexed = TRUE;
  244.             operand[argno].op_index_rn = rn;
  245.             operand[argno].op_index_type = T_LONG;
  246.             argno--;
  247.             break;
  248.  
  249.         case REG:
  250.             sprintf( str, "%s", reg_sym( rn, type ) );
  251.             break;
  252.  
  253.         case REGDEF:
  254.             sprintf( str, "*%s", reg_sym( rn, type | T_POINTER ) );
  255.             break;
  256.  
  257.         case AUTODEC:
  258.             if ( rn == SP )
  259.             sprintf( str, "@arg@" );
  260.             else
  261.             sprintf( str, "*(--%s)",
  262.                 reg_sym( rn, type | T_POINTER) );
  263.             break;
  264.  
  265.         case AUTOINC:
  266.             if ( rn != PC ) {
  267.             sprintf( str, "*%s++",
  268.                 reg_sym( rn, type | T_POINTER ) );
  269.             } else {
  270.             /* immediate values */
  271.             switch ( type & ~T_UNSIGNED ) {
  272.             case TYPB:
  273.                 argval = getdisp(addr, 1, rn, amode);
  274.                 addr += 1;
  275.                 break;
  276.  
  277.             case TYPW:
  278.                 argval = getdisp(addr, 2, rn, amode);
  279.                 addr += 2;
  280.                 break;
  281.  
  282.             case TYPL:
  283.                 argval = getdisp(addr, 4, rn, amode);
  284.                 addr += 4;
  285.                 break;
  286.  
  287.             default:
  288.                 printf( "ERR: strange-autoinc %d\n", type );
  289.                 break;
  290.             }
  291.             sprintf( str, "%d", argval );
  292.             }
  293.             break;
  294.  
  295.         case AUTOINCDEF:
  296.             if ( rn == PC ) {
  297.             /* immediate deferred */
  298.             argval = getdisp(addr, 4, rn, amode);
  299.             addr += 4;
  300.             sprintf( str, "*%d", argval );
  301.             } else {
  302.             sprintf( str, "**(%s++)",
  303.                 reg_sym( rn, type | T_POINTER ) );
  304.             }
  305.             break;
  306.  
  307.         case BYTEDISP:
  308.             argval = getdisp(addr, 1, rn, amode);
  309.             regdisp( rn, argval, type, FALSE, str );
  310.             addr += 1;
  311.             break;
  312.  
  313.         case BYTEDISPDEF:
  314.             ;
  315.             argval = getdisp(addr, 1, rn, amode);
  316.             regdisp( rn, argval, type, TRUE, str );
  317.             addr += 1;
  318.             break;
  319.  
  320.         case WORDDISP:
  321.             argval = getdisp(addr, 2, rn, amode);
  322.             regdisp( rn, argval, type, FALSE, str );
  323.             addr += 2;
  324.             break;
  325.  
  326.         case WORDDISPDEF:
  327.             ;
  328.             argval = getdisp(addr, 2, rn, amode);
  329.             regdisp( rn, argval, type, TRUE, str );
  330.             addr += 2;
  331.             break;
  332.  
  333.         case LONGDISP:
  334.             argval = getdisp(addr, 4, rn, amode);
  335.             regdisp( rn, argval, type, FALSE, str );
  336.             addr += 4;
  337.             break;
  338.  
  339.         case LONGDISPDEF:
  340.             ;
  341.             argval = getdisp(addr, 4, rn, amode);
  342.             regdisp( rn, argval, type, TRUE, str );
  343.             addr += 4;
  344.             break;
  345.         }
  346.         }
  347.         operand[argno].op_argval = argval;
  348.     }
  349.  
  350.     /* print the decompiled instruction */
  351.  
  352. #define doindex( i ) if ( operand[i].op_indexed ) printf( "[%s]", \
  353.         reg_sym( operand[i].op_index_rn, operand[i].op_index_type ) )
  354.  
  355.     switch( op->coptype ) {
  356.  
  357.     case MACRO:   /* print macro code */
  358.     case COMP:
  359.     case TEST:
  360.     case BBRANCH:
  361.     case CBRANCH:
  362.         printf( "\t%s\t", op->cop1 );
  363.         for ( argno = 0; argno < op->numargs; argno++ ) {
  364.         if ( argno != 0 )
  365.             printf( "," );
  366.         printf( "%s", operand[argno].opstring );
  367.         doindex(argno);
  368.         }
  369.  
  370.         if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) {
  371.         insaddr = addr;
  372.         for (argno = 0; argno <= argval; argno++) {
  373.             offset = get_word( addr );
  374.             addr += 2;
  375.             printf( "\n\t\tC%04d", offset+insaddr );
  376.         }
  377.         }
  378.         printf( "\n" );
  379.         break;
  380.  
  381.     case A1OPA0:
  382.         printf( "\t%s", operand[1].opstring );
  383.         doindex(1);
  384.         printf( "%s", op->cop1 );
  385.         printf( "%s", operand[0].opstring );
  386.         doindex(0);
  387.         printf( ";\n" );
  388.         break;
  389.  
  390.     case A2EQ1OP0:
  391.         printf( "\t%s", operand[2].opstring );
  392.         doindex(2);
  393.         printf( " = %s", operand[1].opstring );
  394.         doindex(1);
  395.         printf( "%s", op->cop1 );
  396.         printf( "%s", operand[0].opstring );
  397.         doindex(0);
  398.         printf( ";\n" );
  399.         break;
  400.  
  401.     case A0OP:
  402.         printf( "\t%s", operand[0].opstring );
  403.         doindex(0);
  404.         printf( "%s;\n", op->cop1 );
  405.         break;
  406.  
  407.     case OPONLY:
  408.         printf( "\t%s;\n", op->cop1 );
  409.         break;
  410.  
  411.     case CALLS:
  412.         printf( "\t@val@ = %s", operand[1].opstring );
  413.         doindex(1);
  414.         printf( "( @%s args@ );\n", operand[0].opstring );
  415.         break;
  416.  
  417.     case PUSH:
  418.         printf( "\t@arg@ = %s", operand[0].opstring );
  419.         doindex(0);
  420.         printf( ";\n" );
  421.         break;
  422.  
  423.     case PUSHA:
  424.         printf( "\t@arg@ = &%s", operand[0].opstring );
  425.         doindex(0);
  426.         printf( ";\n" );
  427.         break;
  428.  
  429.     case EXTZV:
  430.         printf( "\t%s", operand[3].opstring );
  431.         doindex(3);
  432.         printf( " = " );
  433.         if ( operand[0].op_argval != 0 ) {
  434.         printf( "( %s", operand[2].opstring );
  435.         doindex(2);
  436.         printf( " >> %d )", operand[0].op_argval );
  437.         } else {
  438.         printf( "%s", operand[2].opstring );
  439.         doindex(2);
  440.         }
  441.         if ( operand[1].op_argval != 32 )
  442.         printf( " & 0x%x;\n",
  443.                0x7fffffff >> ( 31 - operand[1].op_argval ) );
  444.         else
  445.         printf( ";\n" );
  446.     }
  447.     }
  448. }
  449.  
  450.  
  451. /*
  452.  * Print the displacement of an instruction that uses displacement
  453.  * addressing.
  454.  */
  455. static int
  456. getdisp(addr, nbytes, rn, mode)
  457. address addr;
  458. int nbytes;
  459. int rn;
  460. int mode;
  461. {
  462.     int argval;
  463.  
  464.     switch (nbytes) {
  465.     case 1:
  466.     argval = get_byte( addr );
  467.     break;
  468.  
  469.     case 2:
  470.     argval = get_word( addr );
  471.     break;
  472.  
  473.     case 4:
  474.     argval = get_long( addr );
  475.     break;
  476.     }
  477.     if (rn == PC && mode >= BYTEDISP) {
  478.     argval += addr + nbytes;
  479.     }
  480.     return argval;
  481. }
  482.  
  483. static
  484. regdisp( rn, offset, type, defr, str )
  485. int rn, offset, type, defr;
  486. char *str;
  487. {
  488.     char *ds;
  489.  
  490.     if ( defr )
  491.     ds = "*";
  492.     else
  493.     ds = "";
  494.  
  495.     switch ( rn ) {
  496.  
  497.     /* arguments */
  498.     case AP:
  499.     if ( offset < 0 )
  500.         printf( "ERR: bad argument offset %d\n", offset );
  501.     else
  502.         sprintf( str, "%s%s", ds, arg_sym( offset, type ) );
  503.     break;
  504.  
  505.     /* locals */
  506.     case FP:
  507.     if ( offset > 0 )
  508.         printf( "bad local offset %d\n", offset );
  509.     else
  510.         sprintf( str, "%s%s", ds, loc_sym( -offset, type ) );
  511.     break;
  512.  
  513.     case PC:
  514.     if ( defr )
  515.         printf( "ERR: PC deferred\n" );
  516.     sprintf( str, "G%04d", offset );
  517.     break;
  518.  
  519.     /* everything else */
  520.     default:
  521.     sprintf( str, "%s%s->O%03d%s", ds, reg_sym( rn, type | T_POINTER ),
  522.         offset, typesuf[ type ] );
  523.     break;
  524.     }
  525. }
  526.